






Cool Edit
        Version 1.51











File Filters (*.FLT)
Transform Effects (*.XFM)


Application
Programmer's
Interface


File Filters API 						       Making your own file formats

Cool Edit can support any number of file formats.  New file formats can be written by following this API.  A file 
filter is nothing more than a DLL with the following exported functions that Cool Edit calls to do the reading 
(decoding) and writing (coding) of audio data.

When Cool Edit starts, it checks the program directory for any files ending in .FLT.  If it finds any, it checks to 
see if the file contains the function QueryCoolFilter, and if so, it calls that function.  If the return value is 
C_VALIDLIBRARY, then it is assumed to be a valid file format DLL.

When reading an audio file, the function FilterUnderstandsFormat() is called first to see if your file filter can read 
the given file.  If it can, then OpenFilterInput() is called, and then FilterCanReadSpecial() and 
FilterReadSpecial() if the QF_READSPECIALFIRST flag is set.  Audio data is then read in chunks of the size 
specified by calling ReadFilterInput().  If QF_READSPECIALLAST is set, then the special read functions are 
called after all audio data is read in.  Finally, the CloseFilterInput() function is called when all is complete.  The 
functions FilterOptions(), FilterOptionsString(), and FilterGetFileSize() may be called at any time while the input 
file is open.

When writing an audio file, the function FilterGetOptions() may be called at any time if the 
QF_HASOPTIONSBOX flag is set so the user can choose any filter specific options (eg A-Law, mu-Law or 
Linear in the case of .AU files, or 2-bit, 3-bit, or 4-bit compression in the case of DVI compressed files).  The 
GetSuggestedSampleType() function is called to ensure that the file filter can write data in the format that Cool 
Edit will be presenting.  If a different sample type is specified, it will be converted to the desired type before 
being saved.  OpenFilterOutput() is called to initiate the writing process.  As in reading, the special write 
functions may be called before or after writing the audio data depending on the flags set.  Audio data is written 
by calling the WriteFilterOutput() function in blocks of the size specified by your filter at open time.  Once 
everything is written, CloseFilterOutput() is called and writing is complete.

The FilterGetOptions() function should call up a dialog box for the user to choose the format options.  The 
dialog box template should be a resource in the file filter DLL, thus it can be totally defined by the author of the 
DLL.

The sample .AU file filter gives an example of writing a file filter that has multiple options.  You can use these 
files as a template for creating your own file formats.

All functions should be declared as FAR PASCAL __export.

Overview of Functions called by Cool Edit
QueryCoolFilter	Returns information about the type of file filter
FilterGetFileSize	Returns the number of audio data bytes that are allowed to read from the file.
FilterUnderstandsFormat	Returns TRUE if the given file is of a format that this filter understands
GetSuggestedSampleType	Returns the desired sample format for writing
FilterGetOptions	Brings up a dialog box to choose options for the filter if options supported
FilterOptions	Returns the options DWORD for the currently opened file
FilterOptionsString	Returns a readable text description of the filter options
FilterCanReadSpecial	Returns TRUE if this file format can read special extra non-audio data
FilterCanWriteSpecial	Returns TRUE if this file format can write special extra non-audio data
FilterReadSpecial	Reads the requested special non-audio data from the file
FilterWriteSpecial	Writes the special non-audio data to the file
OpenFilterInput	Open the specified file for reading
ReadFilterInput	Read a specified number of bytes from the input audio stream
CloseFilterInput	Close the input file
OpenFilterOutput	Open the specified file for writing
WriteFilterOutput	Write a specified number of bytes to the output audio stream
CloseFilterOutput	Close the output file



int QueryCoolFilter( lpcq )	Required

COOLQUERY far * lpcq	Structure to be filled with all information pertaining to the file filter.

This function should fill the COOLQUERY structure with information about the file filter.

Returns:  C_VALIDLABRARY if successful, zero otherwise.

The COOLQUERY data structure is defined as:

char szName[24]	Textual description of file filter that will show in the File Open and File Save dialog boxes.
char szCopyright[80]	Any copyright information you care to put in for your DLL.  This information is displayed as the file is 
being loaded or saved.
WORD Quad32	Use the R_xxxx constants ORed together to form the sample rates supported by this filter.
WORD Quad16	4-Channel, 16-bit samples
WORD Quad8	4-Channel, 8-bit samples
WORD Stereo8 	Stereo, 8-bit samples
WORD Stereo12  	Stereo, 12-bit samples
WORD Stereo16  	Stereo, 16-bit samples
WORD Stereo24  	Stereo, 24-bit samples
WORD Stereo32  	Stereo, 32-bit samples
WORD Mono8    	Mono, 8-bit samples
WORD Mono12	Mono, 12-bit samples
WORD Mono16	Mono, 16-bit samples
WORD Mono24	Mono, 24-bit samples
WORD Mono32  	Mono, 32-bit samples
DWORD dwFlags	Use the QF_xxxx flags ORed together to provide special information about what functions are 
supported by your filter, etc. and so on.  See  below for a list of QF_xxxx constants.
char szExt[4];	3-character default extension, in caps, followed by a NULL character
long lChunkSize;	Size of chuncks (in bytes) prefered when Cool Edit calls your read and write functions

Constants for Mono/Stereo/Quad 8/12/16/24/32 fields:
R_5500	Low quality, 5500 Hz
R_11025	AM radio quality, 11 KHz
R_22050	Radio quality, 22 KHz
R_32075	FM radio quality, 32 KHz (also valid for 32000 Hz)
R_44100	CD quality, 44.1 KHz
R_48000	DAT quality, 48 KHz

Constants for dwFlags field:
QF_RATEADJUSTABLE	File filter can handle adjustable rates, not just the standards
QF_CANSAVE	File filter supports saving (writing)
QF_CANLOAD	File loading (reading) supported
QF_UNDERSTANDSALL	File filter can read any file at all (used for PCM)
QF_READSPECIALFIRST	Special information should be read before data
QF_READSPECIALLAST	Special information should be read after data
QF_WRITESPECIALFIRST	Special information should be written before data
QF_WRITESPECIALLAST	Special information should be written after data
QF_HASOPTIONSBOX	This format supports multiple options
QF_NOASKFORCONVERT	Set to bypass asking for conversion if original in different rate, ie auto convert sample type
QF_NOHEADER	Set if this is a raw data format with no header

This function must return the value C_VALIDLIBRARY if everything is successful, otherwise it should return zero.


BOOL FilterUnderstandsFormat( lpszFilename )	Required

LPSTR lpszFilename	    File name of file to test for understanding of.

Cool Edit calls this function to determine if the given file can be read by the file filter.  You may need to open the file and read in the 
first few bytes to verify that the header is correct for your format.  For headerless formats, you may just need check the filename 
extension to determine file validity.

Returns:  TRUE if this file filter understands the format of szFilename, FALSE otherwise.


void GetSuggestedSampleType( lplSamprate, lplwBitsPerSample, lpwChannels )
		Required if Writing

LONG FAR * lplSamprate	Sample rate
WORD FAR * lpwBitsPerSample	Bits per Sample (8 or 16)
WORD FAR * wChannels	Channels (1 or 2)

Called with the current format of the waveform that is about to be saved.  If this format is not supported, return the closest format that 
is supported, and Cool Edit will prompt the user if they wish to convert to this format before saving.  Return zero in any of the values 
to indicate that this parameter does not matter.  For example, if this format handles all sample rates, set *lplSamprate to zero.


HANDLE OpenFilterOutput( lpszFilename, lSamprate, wBitsPerSample,
	wChannels, lSize, lplChunkSize, dwOptions )	Required if Writing

LPSTR lpszFilename	File to open for writing
LONG lSamprate		Sample rate in Hz	
WORD wBitsPerSample	Sample size (currently 8 or 16)
WORD wChannels		Number of channels (currently 1 or 2)
LONG lSize		Total amount of data to be written, in bytes.  samples = lSize*wBitsPerSample/8/wChannels
LONG FAR * lplChunkSize	Cool Edit will pass this value in lBytes to WriteFilterOutput()
DWORD dwOptions	Options string returned from FilterGetOptions().  Zero indicates the default should be used

A user defined type should be allocated and the handle returned.  The user defined type should contain all variables that are used in 
the writing of files of this format.  It will be passed in too all functions pertaining to writing.  The output file should be opened for 
writing, overwriting any existing file of the same name since the user has already confirmed that the file name is correct.  The user 
defined type should at the very least contain a handle to the opened file.  The *lplChunkSize parameter should be filled with the 
desired size of a chunk of audio data that WriteFilterOutput() would like.  Set *lplChunkSize to 16384 if the chunk size doesn't matter.  
The dwOptions parameter contains any specific options that the user chose when FilterGetOptions() was called.  If the user never 
called this funciton, dwOptions will be zero, in which case some default should be used. This function will only be called if the 
QF_CANLOAD flag is set.

Returns:  Valid handle to some internal output file structure, NULL file not opened for output for any reason.


void CloseFilterOutput( hOutput )	Required if Writing

HANDLE hOutput		Handle of user defined output structure

No more data is to be writtin out, and the file should be cleanly closed and the user defined structure referred to by hOutput should be 
freed.  As far as Cool Edit is concerned, the file has completed.  The user may have hit Cancel during the write process, in which 
case this function may be called prematurely.  If this is the case, the file should be cleaned up as much as possible so it can still be 
read, otherwise it should be deleted.


DWORD WriteFilterOutput( hOutput, lpbData, lBytes)	Required if Writing

HANDLE hOutput		Handle of user defined output structure
BYTE FAR *lpbData	Data to be written (format was given in call to OpenFilterOutput() )
LONG lBytes		Number of bytes in lpbData to be written

All data in lpbData should be written out to the file.  The file handle should be part of the user defined structure specified by hOutput.

Returns:  Number of bytes actually written.  Once this value is less than lBytes, or is zero, then Cool Edit will stop passing data to be 
written, and will call CloseFilterOutput().



HANDLE OpenFilterInput( lpszFilename, lplSamprate, lpwBitsPerSample,
	lpwChannels, hWnd, lplChunkSize )	Required if Reading

LPSTR lpszFilename		File to open for writing
LONG FAR * lplSamprate		Sample rate in Hz	
WORD FAR * lpwBitsPerSample	Sample size (currently 8 or 16)
WORD FAR * lpwChannels		Number of channels (currently 1 or 2)
HWND hWnd			Parent window - use to display error messages if needed
LONG FAR * lplChunkSize		Cool Edit will pass this value in lBytes to ReadFilterInput()

A user defined type should be allocated and the handle returned.  The user defined type should contain all variables that are used in 
the reading of files of this format.  It will be passed in too all functions pertaining to reading.  The actual sample format should be filled 
into the lplSamprate, lpwBitsPerSample, and lpwChannels parameters.  Fill lplChunkSize with the size of chunks you want 
ReadFilterInput to be called with.  Use the hWnd value as a parent window if any custom dialogs or anything are used here.  Custom 
dialogs for configuring should be called from the FIlterGetOptions() function instead of here.  This function will only be called if the 
QF_CANSAVE flag is set.

Returns:  A handle to the user defined structure used in reading, or NULL if the file could not be opened.


DWORD FilterGetFileSize( hInput )	Required if Reading

HANDLE hInput		Handle to user defined input structure, allocated during OpenFilterInput()

The size of the audio data in the file, in bytes, should be returned.  This function is only called after OpenFilterInput succeeds.

Returns:  The size of the audio data in bytes.



DWORD ReadFilterInput( hInput, lpbData, lBytes)	Required if Reading

HANDLE hOutput		Handle of user defined input structure
BYTE FAR *lpbData	Filled with newly read in data
LONG lBytes		Number of bytes in lpbData that should be read

lBytes bytes of audio data should be read into lpbData.  The file handle should be part of the user defined structure specified by 
hInput.  

Returns:  Number of bytes actually read.  Once this value is less than lBytes, or is zero, then Cool Edit will stop passing data buffers 
to be read into, and will call CloseFilterInput().


void CloseFilterInput( hInput )	Required if Reading

HANDLE hInput		Handle of user defined input structure

No more data is going to be read in.  The file should be cleanly closed and the user defined structure referred to by hInput should be 
freed.  As far as Cool Edit is concerned, the file has completed reading in.  The user may have hit Cancel during the read process, in 
which case this function may be called prematurely.


DWORD FilterGetOptions(	hWnd, hInst, lSamprate, wChannels, 
	wBitsPerSample, dwDefaultOptions )	Optional

HWND hWnd		Handle to use as parent window of options dialog box
HINSTANCE hInst		Instance of your DLL so you can access an options dialog box template
LONG lSamprate		Sample rate of audio that will be saved
WORD wChannels		Number of channels in audio that will be saved
WORD wBitsPerSample	Bits per sample in audio that will be saved
DWORD dwDefaultOptions	Previous options settings, or zero to indicate defaults should be set.

If the QF_HASOPTIONSBOX flag is set, then the user may decide to change the file filter's parameters before saving.  If so, this 
function is called.  This function should in turn call up an options dialog box so the user may change the options.  The options dialog 
box should default to the options specified by dwDefaultOptions.  All options should fit within a single DWORD.  The options 
DWORD should never be zero, since zero indicates that the default should be used.

Returns:  Return zero if no options box is supported, otherwise return a valid DWORD containing all the options that the user chose.  
This options DWORD will be passed to OpenFilterOutput().


DWORD FilterOptions( hInput )	Optional

HANDLE hInput		Handle to user defined input structure

If file filter supports multiple options, then this function should return the current options settings for the opened input file.  This value 
will be used if the file is subsequently saved again in the same format, or if the Options dialog box is called up through 
FilterGetOptions().

Returns:  Return zero if no options box is supported, othrwise return a valid DWORD containing the current options settings for the 
input file.


DWORD FilterOptionsString( hInput, lpszString )	Optional

HANDLE hInput		Handle to user defined input structure
LPSTR lpszString		String to hold text of options setting

The lpszString parameter should be filled with a textual description of the current options settings.  Currently this information is 
displayed for the user when "Show Info" is checked while choosing a file to open.

Return:  Returns zero, and lpszString set to the empty string, if no options box is supported.  Otherwise, a valid DWORD containing 
the current options settings should be returned.



DWORD FilterCanWriteSpecial( hOutput, wType )	Optional

HANDLE hOutput		Handle to user defined ouptut type
WORD wType		One of the SP_ types

If the QF_WRITESPECIALFIRST or QF_WRITESPECIALLAST flag is set, this function is called to see if the requested type is 
handled by your file fitler.  Some file formats support extra information besides just waveform data.  If this is the case, the requests 
from Cool Edit to write the data can be asked before the audio data, or after, depending on the QF_ flag that is set.

Return:  Zero if the requested type is not supported, or 1 if the type is supported by your file filter.



DWORD FilterWriteSpecial( hOutput, wType, lpszData, dwSize )	Optional

HANDLE hOutput		Handle to user defined ouptut type
WORD wType		One of the SP_ types
LPSTR lpszData		Data to be written
DWORD dwSize		Number of bytes of data to be written, includes null terminator for strings

The special information presented by this function should be either written to the output file, or saved in the user defined output 
structure to be written out when CloseFilterOutput() is called.  The data pointed to by lpszData is formatted differently depending on 
the type.  Following is a list of the current types and formatting for lpszData:

wType	Data formated as	Description				
SP_IART	Zero terminated string	Original Artist string, single line
SP_ICMT	Zero terminated string w/ LF's	Comments string, multiple lines
SP_ICOP	Zero terminated string	Copyright string, single line
SP_ICRD	Zero terminated string	Creation date string, single line
SP_IENG	Zero terminated string	Engineers string, single line
SP_IGNR	Zero terminated string	Genre string, single line
SP_IKEY	Zero terminated string	Key words string, single line
SP_IMED	Zero terminated string	Original Medium string, single line
SP_INAM	Zero terminated string	Name string, single line
SP_ISFT	Zero terminated string	Software Package string, single line
SP_ISRC	Zero terminated string	Digitization source string, single line
SP_ITCH	Zero terminated string	Digitizer/Technition string, single line
SP_ISBJ	Zero terminated string w/ LF's	Subject string, multiple lines
SP_ISRF	Zero terminated string	Source Reference string, single line
SP_DISP	<clipboard type> <data>	Clipboard formatted data (eg CF_BITMAP, CF_TEXT)
SP_CUE   	Array of struct cue_type's	Cue list
SP_LTXT  	Array of struct ltxt_type's	Additional information for cue list entries, like length information
SP_NOTE  	List of <id><zero-term-string>	Comments for cue list entries
SP_LABL  	List of <id><zero-term-string>	Labels for cue list entries
SP_PLST  	Array of struct play_type's	Play List

Returns:  The number of bytes processed


DWORD FilterCanReadSpecial( hInput, wType )	Optional

HANDLE hOutput		Handle to user defined ouptut type
WORD wType		One of the SP_ types

If the QF_READSPECIALFIRST or QF_READSPECIALLAST flag is set, this function is called to see if the requested type is 
handled by your file fitler.  Some file formats support extra information besides just waveform data.  If this is the case, the requests 
from Cool Edit to read the data can be asked before or after the audio data, depending on the QF_ flag that is set.

Return:  Zero if the requested type is not supported, or the number of bytes needed for the specific type. 
	For the SP_CUE type, return the number of cue list entries.
	For the SP_PLST type, return the number of play list entries.


DWORD FilterReadSpecial( hInput, wType, lpszData, dwSize )	Optional

HANDLE hOutput		Handle to user defined ouptut type
WORD wType		One of the SP_ types
LPSTR lpszData		Data buffer
DWORD dwSize		Number of bytes of data to read into buffer

If any special information exists in the file and is handled by your file format, you can either read it all in during OpenFilterInput(), or 
when it is requested through this function.  Cool Edit will call this function either before or after the audio data is read depending on 
which of the QF_READSPECIALFIRST or QF_READSPECIALLAST flags are set.  The number of bytes requested should be read 
in from the file, or copied from the user defined input structure.  The various types and the format of lpszData for each type are listed 
in the FilterWriteSpecial() function.

Returns:  The number of bytes actually read.



Structures

Following are the structures that are used in reading and writing files.  Most have to do with the transfer of special types of extra data 
(data that is not audio).  For more information on specific special types, see the RIFF specification, since the format of the data 
closely parallels that in the specification.  Cool Edit actually only supports 8 and 16 bit audio in mono and stereo formats - any sample 
rate.  The COOLQUERY type allows for other formats though.

typedef DWORD FOURCC;         	// a four character code placed into a single DWORD (lsb first)

struct cue_type 
{	DWORD dwName;		// A unique value identifying this cue entry
	DWORD dwPosition;	// Not used by Cool Edit
	FOURCC fccChunk;		// currently always 'data'
	DWORD dwChunkStart;	// always zero
	DWORD dwBlockStart;	// always zero
	DWORD dwSampleOffset;	// Sample offset of cue position
};

struct ltxt_type
{	DWORD dwName;		// A cue dwName to identify which cue entry this info belongs to
	DWORD dwSampleLength;	// Number of samples long for the cue entry (zero for a cue point, more for a range)
	FOURCC fccPurpose;	// (fourcc code, like 'mark')
	WORD wCountry;		// Zero to ignore
	WORD wLanguage;		// Zero to ignore
	WORD wDialect;		// Zero to ignore
	WORD wCodePage;	// Zero to ignore
};

struct play_type 
{	DWORD dwName;		// A cue dwName to identify which cue entry to play
	DWORD dwLength;		// Length in samples (range starts at cue's start point to cue start point + dwLength)
	DWORD dwLoops;		// Number of times to loop
};

typedef struct coolquery_tag
{	char szName[24];		// Text description of file filter that shows in File Open and Save dialogs
	char szCopyright[80];	// Any copyright info, will display while file loads or saves
	WORD Quad32;		// Bit field of supported rates of quadraphonic 32-bit audio
	WORD Quad16;		// Bit field of supported rates of quadraphonic 16-bit audio
	WORD Quad8;		// Bit field of supported rates of quadraphonic 8-bit audio
	WORD Stereo8;    		// Bit field of supported rates of stereo 8-bit audio
	WORD Stereo12;   		// Bit field of supported rates of stereo 12-bit audio
	WORD Stereo16;   		// Bit field of supported rates of stereo 16-bit audio
	WORD Stereo24;   		// Bit field of supported rates of stereo 24-bit audio
	WORD Stereo32;   		// Bit field of supported rates of stereo 32-bit audio
	WORD Mono8;      		// Bit field of supported rates of mono 8-bit audio
	WORD Mono12;	  	// Bit field of supported rates of mono 12-bit audio	
	WORD Mono16;	  	// Bit field of supported rates of mono 16-bit audio
	WORD Mono24;	  	// Bit field of supported rates of mono 24-bit audio
	WORD Mono32;     		// Bit field of supported rates of mono 32-bit audio
	DWORD dwFlags;		// Various flags (see QueryCoolFIlter())
	char szExt[4];		// 3-letter filename extension for file format, zero terminated
	long lChunkSize;		// Desired data block size for reading or writing (in bytes)
} COOLQUERY;



Definitions

#define R_5500   	1		// Rate flags for supported sample types bitfields in COOLQUERY
#define R_11025  	2
#define R_22050  	4
#define R_32075  	8
#define R_44100  	16
#define R_48000  	32
#define R_88200  	64

#define C_VALIDLIBRARY 134	// Returned from QueryCoolFilter() to designate a valid file format
					
		// Flags for dwFlags field of COOLQUERY
#define QF_RATEADJUSTABLE 	1	// All sample rates are valid, not just the standard "R_" ones.
#define QF_CANSAVE 	2	// Set if file filter can write files
#define QF_CANLOAD 	4	// Set if file filter can read files
#define QF_UNDERSTANDSALL 	8	// Set if file filter reads any file format whatsoever (reserved for RAW PCM)
#define QF_READSPECIALFIRST 	16	// Set if extra info should be requested for before reading audio
#define QF_READSPECIALLAST 	32	// Set if extra info should be requested for after reading audio
#define QF_WRITESPECIALFIRST 	64	// Set if extra info should be written for before writing audio
#define QF_WRITESPECIALLAST 	128	// Set if extra info should be written for after writing audio
#define QF_HASOPTIONSBOX 	256	// Set if file format supports multiple options
#define QF_NOASKFORCONVERT 	512	// Set to convert sample type automatically, see GetSuggestedSampleType()
#define QF_NOHEADER 	1024	// Set if this file format does not have a header, if it is just raw data

#define SP_IART  	20
#define SP_ICMT  	21
#define SP_ICOP  	22
#define SP_ICRD  	23
#define SP_IENG  	24
#define SP_IGNR  	25
#define SP_IKEY  	26
#define SP_IMED  	27
#define SP_INAM  	28
#define SP_ISFT  	29
#define SP_ISRC  	30
#define SP_ITCH  	31
#define SP_ISBJ  	32
#define SP_ISRF  	33
#define SP_DISP  	34 	// Clipboard formatted data
#define SP_CUE   	40 	// returns number of cues of size cue_type 
#define SP_LTXT  	41 	// returns number of adtl texts of size 8 (4,id and 4,len)
#define SP_NOTE  	42 	// returns LO=size, HI=number of strings (sz sz sz...)
#define SP_LABL  	43 	// returns LO=size, HI=number of strings (sz sz sz...)
#define SP_PLST  	44 	// returns number of playlist entries size play_type



Transform/Generate Effects API  		         Making your own effects modules

Cool Edit can support any number of transform and generate effects.  New effects can be written by following 
this API.  An effects module is nothing more than a DLL with the following exported functions that Cool Edit calls 
to do the reading and writing of audio data.

When Cool Edit starts, it checks the program directory for any files ending in .XFM.  If it finds any, it checks to 
see if the file contains the function QueryXFM, and if so, it calls that function.  If the return value is 
XFM_VALIDLIBRARY, then it is assumed to be a valid effects module DLL.

The only functions that are required are QueryXfm(), XfmInit(), XfmDestroy(), XfmSetup(), XfmDo(), and some 
sort of DIALOGMsgProc() for the settings dialog.  A custom structure should be defined to hold all effect specific 
data.  This structure must also be communicated to Cool Edit so that various variables in the structure can be 
filled in automatically if you are using the Presets functions.  The COOLINFO structure contains many functions 
that can be called at any time.  These functions can be accessed easily by using the macros defined in 
xfmsdll.c.  Functions include reading and writing audio data, progress meter control, cutting and inserting blank 
data, preset handling, graph handling, FFT functions, and functions for calling other XFM modules.

An internal data structure is used, and defined by the author of the DLL, for storing any relavent information 
pertaining to the effect.  The structure's format is communicated to Cool Edit through the szStructDef element of 
XFMQUERY during QueryXfm().  Never use any global variables - any variables you need should either be 
defined as part of the effect's internal data structure that you define, or allocated locally to the procedure that is 
using them.  This is important since there may be more than one process using the DLL at any given time. 

If you follow the sample code, and use it as a starting point for your own effects module, then you can follow 
some of these guidelines.  Use the DialogToStruct() function to copy data from your instance data structure to 
the dialog box.  Use the StructToDialog() function to copy data from the dialog box back to your data structure.  
You can leave the CopyToDlgItem() and CopyFromDlgItem() functions essentially unchanged (except for 
inserting the name of your custom structure).  These two functions copy the handles to your custom data 
structure, and to the COOLINFO structure to a dialog control so that the instance information can be kept for 
your instance.  This way, if mutliple copies of Cool Edit are using the same effects DLL, then the data will not 
get scrambled between them.  The CopyToDlgItem() function is called during the dialog box's 
WM_INITDIALOG, and the CopyFromDlgItem() function is called before any of the data in the custom structure 
or COOLINFO structure is needed.  Include the file xfmsdll.c to gain access to all the COOLINFO structure 
functions that are provided to you by Cool Edit.

All XFM functions should be declared as FAR PASCAL __export.


int QueryXfm( lpxq )	Required

XFMQUERY FAR * lpxq	Structure to be filled with all information pertaining to the effect module

This function should fill the XFMQUERY structure with information about the effect module.

Returns:  XFM_VALIDLABRARY if successful, zero otherwise.

The XFMQUERY data structure is defined as:
char szName[40]	Text name of the effect that will appear in the menu bar
char szCopyright[80]	Any copyright information you care to put in for your DLL
char szToolHelp[70]	Text to be shown in toolbar quick-help
WORD wSupports	Combination of XFM_ flags for mono and stereo 8 or 16 bit
DWORD dwFlags	Combination of the XF_ flags for describing module
DWORD dwUserDataLength	Length of transform's internal data structure
char szStructDef[48]	Array of chars representing types of data in internal data structure
char szPresetDef[48]	Array of 'y' or 'n' representing whether or not to include data item in presets saving

Constants for the wSupports field:
XFM_MONO8	Effect supports Mono 8-bit data
XFM_STEREO8	Effect supports Stereo 8-bit data
XFM_MONO16	Effect supports Mono 16-bit data
XFM_STEREO16	Effect supports Stereo 16-bit data

Constants for the dwFlags field:
XF_TRANSFORM    	This function works with highlighted audio, and belongs in the Transform menu
XF_GENERATE	This function generates new wave data, and belongs in the Generate menu
XF_USESPRESETSAPI	Has a presets box (and uses the presets/scripts functions)
XF_USESGRAPHAPI	Has one or more graph controls (and uses the built in graph control functions)
XF_MUSTHIGHLIGHT 	If set, function only enabled if a selection is highlighted (most common)
XF_MUSTHAVECLIP    	If set, function is grayed if nothing on clipboard
XF_MODIFIESTOENDOFVIEW	Set this if function modifies data outside user's given selection to end of view
XF_MODIFIESTOENDOFFILE	Set this if function modifies data outside user's given selection to end of file
XF_USESFFTAPI	Uses Cool's FFT functions
XF_NOSINGLEEDIT	If set, function is grayed if editing one channel of a stereo waveform (do this if effect changes 
the size of the highlighted data, eg. stretching)

Characters used in the structure definition (szStructDef) to tell Cool Edit the data types in the internal effect data structure:
'c'	char
'i'	16-bit int or WORD
'l'	32-bit long or DWORD
'f'	4-byte float
'd'	8-byte double floating point
'g'	HANDLE to a graph
'h'	HANDLE to globally allocated memory
's'	Array of 256 chars

BOOL XfmInit( ci )	Required

COOLINFO FAR * ci	Cool Edit info structure pointer

This function should do all initialization of the internal data structure that contains all data pertaining to the effect.  The hUserData 
member of ci is a handle to this data.  Basically, this function should lock the hUserData member, casting it to the internal data type, 
and fill all the members with default info, and finally unlock the handle.

Returns:  TRUE if all was initialized OK, FALSE if there was an error.




BOOL XfmDestroy( ci )	Required

COOLINFO FAR * ci	Cool Edit info structure pointer

All internally allocated data should be freed (eg globally allocated handles) or destroyed (eg graphs).  Use the hUserData member of 
ci to access any internal data.

Returns:  TRUE if all was sucessfully destroyed, FALSE otherwise.


BOOL XfmSetup( hWnd, hInst, ci )	Required

HWND hWnd		Handle to a parent window for your setup dialog box
HINSTANCE hInst		Instance handle for this DLL so you can access resources
COOLINFO FAR * ci	Cool Edit info structure pointer

This function should call up a settings dialog.  The dialog box template should be compiled with the DLL, and can be accessed using 
the hInst parameter.  Below is a sample XfmSetup() function that should suffice for any module.  IDD_TRANSFORM is the dialog 
box ID, and the dialog box message proc is exported with ordinal 100.  The lParam given to the dialog box proc during 
WM_INITDIALOG will be a far pointer to the COOLINFO structure.

BOOL FAR PASCAL __export XfmSetup(HWND hWnd, HINSTANCE hInst, COOLINFO far *ci)
{	int nRc;
	FARPROC lpfnDIALOGMsgProc;
	lpfnDIALOGMsgProc = GetProcAddress(hInst,(LPCSTR)MAKELONG(100,0));
	nRc = DialogBoxParam(	(HINSTANCE)hInst,(LPCSTR)MAKEINTRESOURCE(IDD_TRANSFORM), 
					(HWND)hWnd, (DLGPROC)lpfnDIALOGMsgProc,(DWORD)ci);	
	return nRc;
}

This setup function is called when the user chooses this effect from the menubar.  The dialog box routine should call EndDialog with 
TRUE if the user presses OK, or FALSE if they hit Cancel.  Special care must be taken if more than one settings dialog is to be open 
at one time (if two instances of Cool Edit each have your effect dialog open).  See the example's CopyToDlgItem() and 
CopyFromDlgItem() functions which copy the relavent instance data to a hidden dialog box text control.

Returns:  TRUE to continue on and call XfmDo to run the function, or FALSE if the user hit Cancel in the dialog box.


BOOL XfmDo( ci )	Required

COOLINFO FAR * ci	Cool Edit info structure pointer

This function is what does all the actual work.  The COOLINFO structure contains all information necessary for doing the effect, 
including the portion of the wave that was highlighted, and a handle to this effect's specific internal data structure that should have 
been filled in during the Setup function.  

Returns:  TRUE if all went OK, or FALSE if there was an error.



void DialogToStruct( ci, hWndDlg, lpVars )	Recommended
void StructToDialog( ci, lpVars, hWndDlg )

COOLINFO FAR * ci		Cool Edit info structure pointer
HWND hWndDlg			Settings dialog window handle
EFFECTVARS FAR * lpVars		Pointer to internally defined structure

These functions should transfer data from the dialog box to the user defined data structure, and back.  For example, an effect that 
has a Volume setting would get the text from the "ID_VOLUME" edit control in the dialog and copy it to the lpVars->wVolume 
parameter when calling DialogToStruct.  It would set the "ID_VOLUME" control text to a string containing a value derived from 
lpVars->wVolume when calling StructToDialog.  Since these operations are done frequently, it is best to have them as a separate 
function.  StructToDialog() will be called during the WM_INITDIALOG call, and DialogToStruct() will be called during processing of 
IDOK.



void CopyToDlgItem( hWndDlg, iControl, ci, hVars, lpVars )	Recommended
void CopyFromDlgItem( hWndDlg, iControl, lpci, phVars, plpVars )

HWND hWndDlg			Settings dialog window handle
int iControl			ID of control to store info into (control should be text type and hidden)
COOLINFO FAR * ci		Cool Edit info structure pointer
COOLINFO FAR ** lpci		Pointer to Cool Edit Info Structure pointer
HANDLE hVars			Handle to internally defined structure
HANDLE * phVars			Pointer to handle to internally defined structure
EFFECTVARS FAR * lpVars		Pointer to internally defined structure
EFFECTVARS FAR ** plpVars	Pointer to pointer to internally defined structure

These functions basically copy the handles and pointers used most frequently to a dialog control, and copy data back from the control 
to the appropriate handles and pointers.  During the WM_INITDIALOG, the internal data is locked and the pointer to the data is saved 
in a control's text field.  Whenever any other messages are processed that need this information, it is copied back from the control to 
the locally declared pointers and handles.  Following is the most common implementation for these two functions.  The control ID 
passed into these functions should represent a hidden text field in the dialog box.

void CopyToDlgItem(HWND hWndDlg, int iControl,COOLINFO far *ci,HANDLE hMyVars,  COMPRESS FAR *lpMyVars)
{	char m[80];
	wsprintf(m,"%ld,%d,%ld",lpAmp,hCompress,ci);
	SetDlgItemText(hWndDlg,iControl,m);	
}                                      

void CopyFromDlgItem(HWND hWndDlg, int iControl,  COOLINFO far **ci, HANDLE *hMyVars, COMPRESS FAR **lpMyVars)
{	char m[80];
	char *cursor;         
	GetDlgItemText(hWndDlg,iControl,m,80);
	if (!m[0])
	{	*lpMyVars=NULL;
		*hMyVars=0;
		*ci=NULL;
		return;
	}                            
	cursor=m;
	*lpMyVars=(EFFECTVARS FAR *)longfromstring(&cursor);
	*hMyVars=(HANDLE)longfromstring(&cursor);
	*ci=(COOLINFO far *)longfromstring(&cursor);
}


COOLINFO Structure	

The COOLINFO structure contains everything you may need for performing a transform effect on existing data, or to create new data.  
Following are explanations of the various fields of COOLINFO, though they are not in the same order as declared in the xfms.h file.  
The procedure pointers have not been mentioned - see the following section for info on all procedures.

WORD wChannels	Number of channels in audio data (1 or 2)
WORD wBitsPerSample	Bits per sample (8 or 16)
WORD wBlockAlign	Bytes per sample (1, 2, or 4)
long lSamprate	Sample rate of given audio data
HANDLE hUserData	Handle to user's internal data structure
DWORD dwLoSample	Starting sample offset to transform
DWORD dwHiSample	Ending sample offset to transform
DWORD dwRightSample	Rightmost visible sample on the current display
DWORD dwLeftSample	Leftmost visible sample on the current display
FARPROC lpTestFunction	Nothing.
XFMQUERY FAR * cq	Structure returned by QueryXfm()
char far * szIniFile	INI file to use for storing any data you might want to store.
HFONT hFont	Handle to a small font that you may use in dialog boxes
BOOL bReplacesHighlightedSelection	If set, when generating audio, newly generated audio will replace highlighted sel.
DWORD dwInsertBlankSamples	If nonzero, this many blank samples will be inserted after OK is hit.
BOOL bHasCoprocessor	Set if user has a coprocessor
HINSTANCE hInst	Instance of this DLL
int iScriptFile	-1 if no script running, else script is running
int iScriptDialogStop	Nonzero if "Pause at Dialogs" set for Scripts
BOOL FAR * lpProgressCanceled	Pointer to progress canceled flag.  If flag is set, user hit Cancel in progress meter.


int ReadData( ci, hpData, lOffset, lSize )	COOLINFO function

COOLINFO FAR * ci		Cool Edit info structure pointer
char huge * hpData		Buffer to read into
long lOffset		Offset into user's wave data
long lSize		Number of bytes to read

Read lSize bytes into the buffer hpData from the user's waveform data starting at lOffset bytes into user's data.  The entire amount 
is always read.  Data at offsets below zero, or greater than the length of the file are filled with zeroes for 16-bit data, or 128's for 8-bit 
data. Remember that the this functions works in units of bytes, not samples, and that the formula for converting samples to bytes is 
Bytes = Samples * wBitsPerSample * wChannels / 8.

Returns:  0 if all went OK, otherwise an error occurred.


int WriteData( ci, hpData, lOffset, lSize )	COOLINFO function

COOLINFO FAR * ci		Cool Edit info structure pointer
char huge * hpData		Buffer to write out
long lOffset		Offset into user's wave data
long lSize		Number of bytes to write

Write lSize bytes from the buffer hpData to user's waveform data starting at lOffset bytes into user's data.  The entire amount is 
always written.  Data at offsets below zero are ignored, and data at offsets greater than the length of the file extend the length of the 
user's file.  Remember that the this functions works in units of bytes, not samples, and that the formula for converting samples to 
bytes is Bytes = Samples * wBitsPerSample * wChannels / 8.

Returns:  0 if all went OK, otherwise an error occurred.


void ProgressCreate( ci, cszText, hwndParent )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
LPCSTR cszText			Progress message to display above meter
HWND hwndParent			Parent window of meter display

Create a progress meter to show the user how much of the function has been processed.  This meter automatically estimates the 
total time the function is anticipated to take.  cszText contains text that will be displayed at the top of the meter window, for example, 
"Flanging Selection...".  Set hwndParent to NULL to have the Cool Edit main window be the parent (most common).


BOOL ProgressMeter( ci, dwCurrent, dwTotal )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
DWORD dwCurrent		Measure of current amount done
DWORD dwTotal			Measure of total amount to do

The progress bar is updated with the percentage 100 * dwCurrent / dwTotal.  Usually dwTotal is the total number of bytes that your 
function is going to process, and dwCurrent is the number of bytes processed so far when the function is called.  The progress 
meter must have been created with ProgressCreate() before calling this function.

Returns:  FALSE if user hit Cancel, TRUE if all is going OK.


void ProgressDestroy( ci )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer

Close the progress meter box.  Always remember to close the progress meter if you created one when processing is finished.



void CenterDialog( ci, hWndDlg )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HWND hWndDlg			Handle of settings dialog

Call this function in the WM_INITDIALOG section of your dialog's settings window to center the dialog with respect to the Cool Edit 
window that called it.


BOOL PresetsInit( ci, hWndDlg, cszGroupName )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HWND hWndDlg			Handle of settings dialog
LPCSTR cszGroupName		Name of function

This should be called in the WM_INITDIALOG section of your dialog's settings window if presets are used.  cszGroupName 
identifies a unique name for your function which is used as a key in the INI file for keeping the preset information.  This is usually the 
same as the name of the function given in the XFMQUERY structure.  The szStructDef array of XFMQUERY contains an array of 
characters representing each of the data items in the user defined structure.  szPresetDef contains an array of 'y' and 'n' characteres 
which specify whether or not to include the associated user data item in the preset.  For example, a user defined structure with 4 
integers (szStructDef="iiii") of which only the first 3 should be saved when added to the presets would have szPresetDef equal to 
"yyyn".

The dialog box must have the following IDs for various preset controls:

#define ID_PRESETS	1005	// Single selection sorted list box with Notify flag set
#define ID_PRESETNAME	1006	// Edit control for user to enter new preset name to add or delete
#define ID_ADD		325	// Button with text "Add"
#define ID_DEL		1109	// Button with text "Del"

Returns:  0 if no presets yet exist, or the number of presets if some do exist.  (you can cast the BOOL return type to int).


BOOL HandleID_PRESETS ( ci, hWndDlg, cszGroupName, lParam )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HWND hWndDlg			Handle of settings dialog
LPCSTR cszGroupName		Name of function
LPARAM lParam			lParam passed to settings dialog

Call this function in response to the WM_COMMAND message when wParam is ID_PRESET.  The function returns TRUE if the 
user chose a new preset item (double clicked on a name in the presets box).  The StructToDialog() procedure should be called if 
this is the case to update all the dialog controls with the new data.

case ID_PRESETS:
	if ( HandleID_PRESETS( ci, hWndDlg, TRANSFORMNAME, lParam ) )
	{	StructToDialog( ci, lpMyVars, hWndDlg );
 	}
	break;

Returns:  TRUE if user chose a new preset item, FALSE otherwise.


void HandleID_ADD ( ci, hWndDlg, cszGroupName )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HWND hWndDlg			Handle of settings dialog
LPCSTR cszGroupName		Name of function

Call this function in response to the WM_COMMAND message when wParam is ID_ADD.  The DialogToStruct() function should 
be called before calling HandleID_ADD() to fill the COOLINFO structure with the information in the dialog box controls.

case ID_ADD:
	DialogToStruct(ci, hWndDlg, lpMyVars);
	HandleID_ADD(ci, hWndDlg, TRANSFORMNAME);       
	break; 	 


void HandleID_DEL ( ci, hWndDlg, cszGroupName )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HWND hWndDlg			Handle of settings dialog
LPCSTR cszGroupName		Name of function

Call this function in response to the WM_COMMAND message when wParam is ID_DEL. 

case ID_DEL:
	HandleID_DEL(ci, hWndDlg, TRANSFORMNAME);
	break;


void HandleID_PRESETNAME ( ci, hWndDlg )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HWND hWndDlg			Handle of settings dialog

Call this function in response to the WM_COMMAND message when wParam is ID_PRESETNAME. 

case ID_PRESETNAME:
	HandleID_PRESETNAME(ci, hWndDlg);
	break;	


HANDLE GraphCreate ( ci, iLeft, iRight, iMin, iMax, iLeftVal, iRightVal )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
int iLeft				Leftmost graph coordinate (along x axis)
int iRight				Rightmost graph coordinate
int iMin				Minimum graph value (along y axis)
int iMax				Maximum graph value
int iLeftVal			Value of leftmost point (must be between iMin and iMax)
int iRightVal			Value of rightmost point (must be between iMin and iMax)

This function returns an handle to a graph that is passed to subsequent graph functions.  Graphs are usually created in the XfmInit() 
function, and destroyed in the XfmDestroy() function.  A graph control allows the user to specify any number of points connected by 
a single line that has only one y value for every x value.  

Returns:  Handle to graph if successful, or NULL if no graph was created.
 

void GraphSetDialog ( ci, hGraph, hWndDlg, uiControl, uiDisplay )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
HWND hWndDlg			Handle of settings dialog
UINT uiControl			ID of rectangle control defining boundaries of graph
UINT uiDisplay			ID of static text control for displaying graph point data

This should be called in the WM_INITDIALOG section of your dialog's settings window to attach dialog controls to the graph.  The 
graph must know of a rectangle it can be drawn inside of, and of a text control for displaying graph relevant information, and of the 
handle to the dialog box itself.  uiControl is the ID of a Frame type picture control in the dialog box, while uiDisplay is the ID of a left 
aligned text control in the dialog box.  The graph will automatically fit itself inside the bounds of the rectangle.


int GraphCount ( ci, hGraph )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()

The user can create new points in a graph at any time.  This function returns the total number of points in the graph.

Returns:  The number of points in the graph.


POINT GraphGetPoint ( ci, hGraph, iIndex )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
int iIndex				Point to get (0 to GraphCount() - 1)

Returns a point structure (whose members are .x and .y) that contains the x and y coordinates of the point at the given index.  Index 
values range from 0 for the left hand point on up to the number of points in the graph minus one for the rightmost point.

Returns:  x and y value of point in graph.


void GraphSetPoint ( ci, hGraph, int iIndex, ptPoint, bEndPoint )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
int iIndex				Index of point to set
POINT ptPoint			Coordinates of point to add or set
BOOL bEndPoint			TRUE if this point is the rightmost point (as in adding new points to the end)

Call this function to add new points or change the position of points in the graph.  Not used very often.  You can build a set of points 
for a graph by using this function, but usually the user is the one who creates the points by clicking and dragging.  If the point you are 
adding is a new rightmost point, indicate by setting bEndPoint to TRUE.


double GetValueAt ( ci, hGraph, fXValue )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
double fXValue			X coordinate on graph

Returns the y value at any given point along the x axis of the graph.  Values between points on the graph are linearly interpolated, so 
no matter what x value is given (provided it is between the graph's left and right values given at creation time), a valid value is 
returned.  The function works with double precision floating point values since the y value is interpolated, and may not be an integral 
value.

Returns:  The y value at the given x coordinate.


void GraphDraw ( ci, hGraph, hDC )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
HDC hDC				Device Context of dialog box for drawing graph into

This function should be called in the WM_PAINT routine of the settings window.  The hDC should be the same hDC that was 
returned from BeginPaint().  The code snippet blow illustrates getting the pointer to the user defined structure (lpMyVars), and then 
getting the dialogs device context, drawing the graph, end ending the paint routine.  The graph is a HANDLE type in the users 
structure, and has the code 'g' associated with it in the definition variable szStructDef.

case WM_PAINT:
{	HDC hDC;
    	PAINTSTRUCT ps;
    	CopyFromDlgItem( hWndDlg,IDC_STORAGE, &ci, &hMyVars, &lpMyVars );
         hDC=BeginPaint( hWndDlg, &ps );
         GraphDraw( ci, lpMyVars->hGraph, hDC );
         EndPaint( hWndDlg, &ps );
         return FALSE;
}



void GraphClear ( ci, hGraph )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()

Clear all the points in the graph except for the leftmost and rightmost endpoints.


void GraphInvert ( ci, hGraph )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()

Invert the graph if the graph is indeed invertable.  The graph is invertable if there is exactly one x point for every y point.  When the 
graph is inverted, every x value is swapped with every y value.  The property that there is only one y value for each x value must still 
hold.  Sorry, but no indication is returned if the function inverted the graph or not.


void GraphCopy ( ci, hGraphDest, hGraphSource )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraphDest		Handle to graph to copy into
HANDLE hGraphSource		Handle of graph to copy from

Copy the contents of the source graph to the destination graph.  Both graphs must have already been created using GraphCreate().  


void GraphSetDblClkScales ( ci, hGraph, fScx, fOfx, fMagx, 
	fScy, fOfy, fMagy, wStyle )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
double fScx			Scaling factor for X coordinate
double fOfx			Offset for X coordinate
double fMagx			Precision of X coordinate
double fScy			Scaling factor for Y coordinate
double fOfy			Offset for Y coordinate
double fMagy			Precision of Y coordinate
WORD wStyle			Style (set to 0)

Set the scaling factors that the actual points will be modified by before being displayed in the text box.  The text box whose ID was 
given in the GraphSetDialog() call will display the value of the point when a point is selected.  The value displayed is not the same as 
the integer value of the point, but a value base on the following formula:  DisplayValue = PointValue * fScx + fOfx.  The value of the 
point is multiplied by the scaling factor and added to the offset to get the final value displayed to the user.  The magnitude/precision 
value tells how many decimal places to round the value off to.  For example, fMagx of 10 will round values to one decimal place (eg 
3.1), while fMagx of 100 will round values to two decimal places (eg 3.14).  Values that are not powers of 10 will round according, for 
example fMagx of 4 will give values such as "4", "4.25", "4.5", and "4.75".

The actual data displayed to the user will be this value along with the units given in the GraphSetDblClkNames() function.  The 
wStyle parameter should always be zero.  If it is set to 1, then the final value is converted to decibels (eg 0.5 becomes -3, and 2.0 
becomes +3).



void GraphSetDblClkNames ( ci, hGraph, cszXText, cszXUnits,
	cszYText, cszYUnits )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
LPCSTR cszXText			Name for values along x axis (going left and right)
LPCSTR cszXUnits			Units for values along x axis
LPCSTR cszYText			Name for values along y axis (going up and down)
LPCSTR cszYUnits			Unints for values along y axis

Set the names for the values along the x and y axes, for example, "Input Signal Level" or "Frequency", and the names for the units of 
these, for example, "dB" or "Hz".


int GraphHandleWM_LBUTTONDOWN ( ci, hGraph, ptCursor )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
POINT ptCursor			Coordinate of mouse down point (gained from lParam)

Call this function in response to the WM_LBUTTONDOWN message in the settings dialog.  The lParam parameter can be 
converted to a point since the LOWORD of lParam is the x coordinate, and the HIWORD of lParam is the y coordinate.

case WM_LBUTTONDOWN:
{	POINT here;
    	int whichpoint;
	CopyFromDlgItem( hWndDlg, IDC_STORAGE, &ci, &hMyVars, &lpMyVars );
        	here.x=LOWORD( lParam );
	here.y=HIWORD( lParam );
	whichpoint=GraphHandleWM_LBUTTONDOWN( ci, lpMyVars->hGraph, here );
}

Returns:  The index of the point that is under the mouse.  A new point may have been created if the user clicked in an empty area of 
the graph.   This index will always range from 0 to one minus the number of points in the graph.


int GraphHandleWM_LBUTTONUP ( ci, hGraph, ptCursor )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
POINT ptCursor			Coordinate of mouse up point (gained from lParam)

Call this function in response to the WM_LBUTTONUP message in the settings dialog.  See GraphHandleWM_LBUTTONDOWN 
for more specifics.

Returns:  The index of the point that is under the mouse.


int GraphHandleWM_LBUTTONDBLCLK ( ci, hGraph, ptCursor )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
POINT ptCursor			Coordinate of mouse double click point (gained from lParam)

Call this function in response to the WM_LBUTTONDBLCLK message in the settings dialog.  See 
GraphHandleWM_LBUTTONDOWN for more specifics.

Returns:  The index of the point that is under the mouse.



int GraphHandleWM_MOUSEMOVE ( ci, hGraph, ptCursor )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()
POINT ptCursor			Coordinate of mouse point (gained from lParam)

Call this function in response to the WM_MOUSEMOVE message in the settings dialog.  See GraphHandleWM_LBUTTONDOWN 
for more specifics.

Returns:  The index of the point that is under the mouse.


void GraphDestroy ( ci, hGraph )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hGraph			Handle to graph given by GraphCreate()

Call this function to destroy the graph.  This is usually done in the XfmDestroy() function.  After the graph is destroyed, the handle is 
no longer valid, and all memory used by the graph is freed.


void GetTempName ( ci, szThree, szFilename )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
LPSTR szThree			Three letter identifier for type of temporary file
LPSTR szFilename			Complete filename of temporary file

This function returns the name of a valid unique temporary file name in szFilename.  The user's choice of temporary directory in Cool 
Edit is used as the directory for this file.


HANDLE CreateXfmVars ( ci, cszXfmName )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
LPCSTR cszXfmName		Name of the other effects module

Other effects modules can be used from within your effects module if they exist.  For example, you can possibly use Cool Edit's Filter 
or Amplify functions from within your own.  But since the internal structures for these functions may change over time, you are better 
off just using other XFM modules that you have created.  When called, the external structure is initialized to its defaults (from the 
other module's XfmInit() function).

Returns:  Handle to be used in subsequent calls for identifying the external effect module's data structure


void SetXfmVar ( ci, hVars, iOffset, iLength, lpvMem )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
HANDLE hVars			Handle for use with external transforms (from CreateXfmVars())
int iOffset			Offset into transform's structure
int iLength			Length of data in transform's structure
void far * lpvMem			Memory to copy to transform's structure

Set some data in another effect module's user defined data structure.  After the data is set, the effect may be called using CallXfm().



long CallXfm ( ci, cszXfmName, hVars, 
	dwLoSamp, dwHiSamp, bShowMeter )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
LPCSTR cszXfmName		Name of the other effects module
HANDLE hVars			Handle for use with external transforms (from CreateXfmVars())
DWORD dwLoSamp		Low sample value to work with
DWORD dwHiSamp		High sample value to work with
BOOL bShowMeter			Should the called effect show its progress meter?

Actually call the other effect.  The effect will work with samples from dwLoSamp on up to dwHiSamp.  If your function is displaying a 
progress meter, you will want to set bShowMeter to FALSE so the effect you are calling doesn't try to display its own progress meter 
as well (which would end in total confusion and chaos).

Returns:  Value depends on function being called.  It is the return value from XfmDo() of the effect being called.


void SetWindowType ( ci, wType )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
WORD wType			Type of window

Sets the window type when windowing data for an FFT (when using WindowFFT() and IWindowFFT()).  Window types can be any 
one of the following:

0	Triangular
1	Von Hann
2	Hamming
3	Blackman
4	Cosine Squared
5	Blackman-Harris

The values go from narrowest band but widest sidelobes and gentle slopes to wider bands with smaller sidelobs and steeper slopes.  
In general, Hamming is used most often, but Blackman will give a little steeper slopes.


void WindowFFT ( ci, lpData, iSize, bStereo )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
float far * lpData			Pointer to FFT prepared data (prepare with the SetFFT... functions)
int iSize				Size of FFT (number of data points)
BOOL bStereo			TRUE for stereo, FALSE for mono

Once data is converted from 16-bit or 8-bit audio to floating point data, the floating point data can be windowed before performing the 
FFT.  Windowing the data consists of multiplying each sample by the window values.  Samples near the center are multiplied by 1.0 
while samples near the end are multiplied by smaller values down to but not including 0.  Windowing the data will give a more precise 
measurement of the frequencies present, since the data is assumed to be circular.  Please read about FFTs in other material related 
to Digital Signal Processing for more information.


void IWindowFFT ( ci, lpData, iSize, bStereo )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
float far * lpData			Pointer to FFT prepared data (prepare with the SetFFT... functions)
int iSize				Size of FFT (number of data points)
BOOL bStereo			TRUE for stereo, FALSE for mono

Perform the inverse window on FFT data.  Callint IWindowFFT() right after WindowFFT will result in no change in the original data.  
Instead of multiplying the data by the window coefficients, the data is divided by the window coefficients.



void FFT ( ci, lpData, iSize, iDirection )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
float far * lpData			Pointer to FFT prepared data (prepare with the SetFFT... functions)
int iSize				Size of FFT (number of data points)
int iDirection			1 for FFT, -1 for inverse FFT

Perform an FFT (Fast Fourier Transform)  on the prepared data.  The floating point values will then contain pairs of  {real,imaginery} 
data starting at index 1, so lpData[1] contains the real part of the first bin, and lpData[2] contains the imaginery part of the first bin, 
and so on.  The data going in to the FFT should have been prepared from the original audio data using one of the SetFFT... 
functions.  The largest size of FFT that should be used with this function is a 4096 point FFT, so iSize should never be more than 
4096, and must be a power of 2.

After the FFT is performed, the data can be manipulated, or viewed, or whatever.  If it is manipulated in some way (eg changing the 
phase or amplituded of various frequency components), then the inverse FFT can be performed by setting iDirection to -1, then an 
inverse Window performed by calling IWindowFFT(), and finaly calling the GetFFT... function to convert the floating point data back 
to audio data.  Please read books on Digital Signal Processing for more information on the FFT.


void LFFT ( ci, hpReData, hpImData, lSize, iDirection )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
double huge * hpReData		Pointer to array of lSize doubles representing the Real components
double huge * hpImData		Pointer to array of lSize doubles representing the Imaginery components
long  iSize			Size of FFT (number of data points)
int iDirection			1 for FFT, -1 for inverse FFT

Perform an FFT (Fast Fourier Transform)  on the data.  The largest sized FFT supported depends on the amount of RAM the user 
has, which will be evident when the huge arrays are allocated by your DLL.  On the average, FFT sizes up to 262,144 points can be 
performed successfully on most systems.  The data is zero-based, so hpReData[0] is the first real value part of the first data point for 
example.  The number of data points should only have the factors 2,3,4, and 5.  So an FFT of size 10,000 is fine, since that 10,000 
factors to 5 * 5 * 5 * 5 * 4 * 4.  So, any powers of 2, 3, 4, or 5 are also valid by this rule.

After the FFT is performed, the data can be manipulated, or viewed, or whatever.  If it is manipulated in some way (eg changing the 
phase or amplituded of various frequency components), then the inverse FFT can be performed by setting iDirection to -1.  You must 
provide any windowing necessary on this data, as the only "Large" FFT function provided is this one.


void SetFFT16bit ( ci, lpFloats, lpiAudio, iSize )
void SetFFT8bit ( ci, lpFloats, lpcAudio, iSize )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
float far *lpFloats			Destination array of floating point values for use with FFT functions
int far * lpiAudio			Source array of 16-bit samples
usigned char far * lpcAudio		Source array of 8-bit samples
int iSize				Number of samples to prepare/copy.

Fill an array of complex floats with integer audio data.  There will be twice as many floating point numbers generated as iSize since 
complex numbers require two floats (one for the real part, and one for the imaginery part).  The floats array must be large enough to 
hold iSize*2+1  floating point values (the +1 is because the array is 1 based, not zero based).  iSize integer samples from lpiAudio will 
be converted to iSize complex floating point values in lpFloats.

If preparing 8-bit audio for an FFT, the SetFFT8bit function is used, and character data is read instead of integer data.


void SetStereoFFT16bit ( ci, lpFloats, lpiLeft, lpiRight, iSize )
void SetStereoFFT8bit ( ci, lpFloats, lpcLeft, lpcRight, iSize )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
float far *lpFloats			Destination array of floating point values for use with FFT functions
int far * lpiLeft			Source array of 16-bit samples for left chananel
int far * lpiRight			Source array of 16-bit samples for right channel
usigned char far * lpcLeft		Source array of 8-bit samples for left chananel
unsigned char far * lpcRight		Source array of 8-bit samples for right channel
int iSize				Number of samples to prepare/copy.

Two channels can be converted to one set of floating point data at a time for more efficiency.  This way, two FFTs can be performed 
in parallel.



void SetStereoFFT16bitInterleaved ( ci, lpFloats, lpiAudio, iSize )
void SetStereoFFT8bitInterleaved ( ci, lpFloats, lpcAudio, iSize )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
float far *lpFloats			Destination array of floating point values for use with FFT functions
int far * lpiAudio			Source array of 16-bit samples, left/right interleaved
usigned char far * lpcAudio		Source array of 8-bit samples, left/right interleaved
int iSize				Number of samples to prepare/copy.

Two channels can be converted to one set of floating point data at a time for more efficiency.  This way, two FFTs can be performed 
in parallel.  The source data is interleaved left sample 0, right sample 0, left sample 1, right sample 1, ...

void GetStereoFFT16bitInterleaved ( ci, lpFloats, lpiAudio, iSize, iOp)
void GetStereoFFT8bitInterleaved ( ci, lpFloats, lpcAudio, iSize, iOp )	COOLINFO function

COOLINFO FAR *ci			Cool Edit info structure pointer
float far *lpFloats			Source array of floating point values for use with FFT functions
int far * lpiAudio			Destination array of 16-bit samples, left/right interleaved
usigned char far * lpcAudio		Destination array of 8-bit samples, left/right interleaved
int iSize				Number of samples to prepare/copy.
int iOp				Operation - set this to zero.

Convert floating point FFT data (data gained after doing an inverse FFT) back to interleaved audio.  

To convert FFT data back that was set using SetFFT16bit, simply convert every other floating point value starting with offset 1.  So 
IntegerSample[0] = (int)lpFloats[1], IntegerSample[1] = (int)lpFloats[3], IntegerSample[2] = (int)lpFloats[5] and so on until you have 
IntegerSamploe[iSize-1] = (int)lpFloats[(iSize-1)*2+1]


Definitions

#define XFM_MONO8	1
#define XFM_STEREO8 	2
#define XFM_MONO16	4
#define XFM_STEREO16	8  

#define XFM_HELPFILE "cool.hlp"   // Put your own help file here if you support the [?] Help button

typedef DWORD (CALLBACK*      DWFARPROC)();	// Used for COOLINFO structure functions
typedef void  (CALLBACK*      VFARPROC)();		// Used for COOLINFO structure functions

typedef struct xfmquery_tag
{	char szName[40];  		// Appears in Menu (without elipsis...), eg "Echo" will create the menu item "Echo..."
	char szCopyright[80];	// Appears in the progress meter dialog when processing
	char szToolHelp[70];		// Appears in the quick-help below toolbar icon
	WORD wSupports;	// OR's of XFM_MONO16, XFM_STEREO16, XFM_MONO8, XFM_STEREO8  A
		// function only needs to support MONO and STEREO 16-bit, Cool Edit will do the
		// necessary conversions to work with 8-bit data.
	DWORD dwFlags;		// Any of the XF_ flags OR'd together
				// Must at least have either XF_TRANSFORM, XF_GENERATE or XF_ANALYZE
	DWORD dwUserDataLength;	// Length of transform's internal data
	char szStructDef[48];	// Array of chars representing types in user data area
	char szPresetDef[48];	// Array of chars 'y' to include in presets, 'n' to ignore.	
} XFMQUERY;

#define XFM_VALIDLIBRARY 		150	// This stands for the earliest version of Cool Edit that this API supports

#define XF_TRANSFORM    		1	// This function transforms highlighted audio
#define XF_GENERATE		2	// This function generates new pcm wave data
#define XF_ANALYZE		1024 	// This function analyzes the highlighted audio data

#define XF_USESPRESETSAPI	4	// Has a presets box (and uses the presets/scripts API)
#define XF_USESGRAPHAPI		8	// Uses the built in graph control functions
#define XF_USESFFTAPI		256 	// Uses Cool's FFT functions

#define XF_MUSTHIGHLIGHT 	16  	// If set, function only enabled if a selection is highlighted (normal)
#define XF_MUSTHAVECLIP    	32  	// If set, function is grayed if nothing on clipboard
#define XF_MODIFIESTOENDOFVIEW 	64  	// Set this if function modifies data outside user's given selection
#define XF_MODIFIESTOENDOFFILE 	128 	// Set this if function modifies data outside user's given selection
#define XF_NOSINGLEEDIT		512 	// Do not include if editing only one channel

// See the text for in depth explanations of the various functions your XFM DLL can call.
typedef struct coolinfo_tag
{	WORD wChannels;	// Number of channels
	WORD wBitsPerSample;	// Bit size, 8 or 16 for now
	WORD wBlockAlign;	// Bytes per sample (eg stereo 16-bit = 4)
	long lSamprate;	// Sample rate (8000,11025,22050, etc.) 
	HANDLE hUserData;	// Handle to specialized transform data, depends on DLL
	DWORD dwLoSample;       	// Lowest sample to transform
	DWORD dwHiSample;	// Highest sample
	FARPROC lpTestFunction; 	// Not Used
	XFMQUERY FAR *cq;	// Pointer to query struct

	// General Purpose Tools
	FARPROC lpCenterDialog;	// (HWND hWndDlg, int iUnused)  Center the dialog box
	
	// Reading and Writing audio data
	FARPROC lpReadData;	// (char huge *data,long offset,long amount)
	FARPROC lpWriteData;	// (char huge *data, DWORD offset,DWORD nbytes)	              
	
	// Progress Meter
	BOOL FAR *lpProgressCanceled;  	// if TRUE, user hit Cancel button, you must stop processing NOW
	FARPROC lpProgressMeter; 	// (DWORD dwCurrent, DWORD dwTotal)  percent done is 100*dwCurrent/dwTotal
	FARPROC lpProgressCreate; 	// (LPCSTR szText)  szText is message to indicate type of processing
	FARPROC lpProgressDestroy; 	// (void)  Call to remove progress meter
	


Definitions continued

	// Presets
	char far * szIniFile;    	// Ini file to save preset info into
	FARPROC lpPresetsInit;	
	FARPROC lpHandleID_PRESETNAME;
	FARPROC lpHandleID_PRESETS;
	FARPROC lpHandleID_ADD;
	FARPROC lpHandleID_DEL;    
	
	// Graph control
	FARPROC lpGraphCreate;
	FARPROC lpGraphCount;
	FARPROC lpGraphGetPoint;
	FARPROC lpGraphGetValueAt;
	FARPROC lpGraphDraw;
	FARPROC lpGraphClear;
	FARPROC lpGraphInverse;
	FARPROC lpGraphDestroy;
	FARPROC lpGraphHandleWM_LBUTTONDOWN;
	FARPROC lpGraphHandleWM_LBUTTONUP;
	FARPROC lpGraphHandleWM_LBUTTONDBLCLK;
	FARPROC lpGraphHandleWM_MOUSEMOVE;
	FARPROC lpGraphSetDblClkScales;
	FARPROC lpGraphSetDblClkNames; 
	FARPROC lpGraphSetDialog;	
	
	int iScriptFile;  
	int iScriptDialogStop; 
	HFONT hFont; 	// smaller font for dialogs
	
	// for XF_GENERATE type, must be filled out during XfmSetup
	BOOL bReplacesHighlightedSelection;    	// if TRUE, highlighted selection is deleted before inserting blanks
	DWORD dwInsertBlankSamples;		// the number of samples to generate
	BOOL bHasCoprocessor;		// if TRUE, use fp, otherwise use table lookups and other speedups
	FARPROC lpFFT; 		// perform n-point FFT (radix-2 for now)
	FARPROC lpWindowFFT;
	FARPROC lpIWindowFFT;
	FARPROC lpSetWindowType;  		// 0..5: Triangular, von Hann, Hamming, Blackman, Cosine^2, Blackman-Harris
	FARPROC lpGetTempName; 		// get temporary file name
	
	FARPROC lpSetFFT16bit;
	FARPROC lpSetFFT8bit;
	FARPROC lpSetStereoFFT16bit;
	FARPROC lpSetStereoFFT8bit;
	FARPROC lpSetStereoFFT16bitInterleaved;
	FARPROC lpSetStereoFFT8bitInterleaved;
	FARPROC lpGetStereoFFT16bitInterleaved;
	FARPROC lpGetStereoFFT8bitInterleaved;    
	
	FARPROC lpCreateXfmVars;
	FARPROC lpSetXfmVar;
	DWFARPROC lpCallXfm;
	
	// Delayed writing
	VFARPROC lpDelayWrite;
	VFARPROC lpDelayWriteInit;
	VFARPROC lpDelayWriteDestroy;
	
	HINSTANCE hInst;		// This is the instance of your DLL
	
	FARPROC lpGraphCopy;
	FARPROC lpCutData;
	FARPROC lpInsertBlankData;
	FARPROC lpDeleteXfmVars; 
	
	DWORD dwRightSample;    		// Current viewing screen rightmost sample
	DWORD dwLeftSample;		// and leftmost sample  
	FARPROC lpGraphSetPoint;
	
	DWORD dwExtraFlags;
	FARPROC lpLFFT;		 		
} COOLINFO;

25



